﻿using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Effects;

namespace TheOliver.Controls
{
    public class ImageWall : Panel
    {
        protected override Size ArrangeOverride(Size finalSize)
        {
            if (this.UseClipping)
            {
                // Clipping
                RectangleGeometry cliprect = new RectangleGeometry();
                cliprect.Rect = new Rect(0, 0, finalSize.Width, finalSize.Height);
                this.Clip = cliprect;
            }

            LayoutImages(finalSize);
            return base.ArrangeOverride(finalSize);
        }

        private void LayoutImages(Size availableSize)
        {
            int currentRow = 0;
            int currentColumn = 0;

            foreach (Image image in this.Children.OfType<Image>())
            {
                #region Hover Effect 

                Hover3DBehavior behavior = new Hover3DBehavior();
                behavior.ZHoverValue = (double)this.GetValue(ZHoverValueProperty);
                behavior.Attach(image);

                if ((bool)this.GetValue(ShowShadowProperty))
                {
                    DropShadowEffect ds = new DropShadowEffect();
                    ds.Opacity = .3;
                    ds.BlurRadius = 10.0;
                    ds.Direction = 0.0;
                    ds.ShadowDepth = 20.0;
                    image.Effect = ds;
                }

                #endregion

                double left = currentColumn * (ImageWidth + ImageMargin);
                double top = currentRow * (ImageHeight + ImageMargin);

                if (top + ImageHeight >= availableSize.Height)
                {
                    currentRow = 0;
                    currentColumn++;
                    left = currentColumn * (ImageWidth + ImageMargin);
                    top = currentRow * (ImageHeight + ImageMargin);
                }

                Rect rect = new Rect(
                    left,
                    top,
                    ImageWidth,
                    ImageHeight);

                image.Width = ImageWidth;
                image.Height = ImageHeight;
                image.Arrange(rect);
                image.InvalidateArrange();

                currentRow++;
            }
        }

        private const int C_DefaultRowsPerColumn = 5;
        private const double C_DefaultImageWidth = 160.0;
        private const double C_DefaultImageHeight = 120.0;
        private const double C_DefaultZHover = 200.0;
        private const bool C_DefaultShowShadow = true;
        private const double C_DefaultImageMargin = 8.0;

        #region Properties

        public bool UseClipping
        {
            get { return (bool)GetValue(UseClippingProperty); }
            set { SetValue(UseClippingProperty, value); }
        }

        public static readonly DependencyProperty UseClippingProperty =
            DependencyProperty.Register(
                "UseClipping", 
                typeof(bool), 
                typeof(ImageWall), 
                new PropertyMetadata(true, OnValueChanged));

        public double ImageWidth
        {
            get { return (double)GetValue(ImageWidthProperty); }
            set { SetValue(ImageWidthProperty, value); }
        }

        public static readonly DependencyProperty ImageWidthProperty =
                DependencyProperty.Register("ImageWidth", typeof(double),
                typeof(ImageWall),
                new PropertyMetadata(C_DefaultImageWidth,
                new PropertyChangedCallback(OnValueChanged)));

        public double ImageMargin
        {
            get { return (double)GetValue(ImageMarginProperty); }
            set { SetValue(ImageMarginProperty, value); }
        }

        public static readonly DependencyProperty ImageMarginProperty =
                DependencyProperty.Register("ImageMargin", typeof(double),
                typeof(ImageWall),
                new PropertyMetadata(C_DefaultImageMargin,
                new PropertyChangedCallback(OnValueChanged)));

        public double ImageHeight
        {
            get { return (double)GetValue(ImageHeightProperty); }
            set { SetValue(ImageHeightProperty, value); }
        }

        public static readonly DependencyProperty ImageHeightProperty =
                DependencyProperty.Register("ImageHeight", typeof(double),
                typeof(ImageWall),
                new PropertyMetadata(C_DefaultImageHeight,
                new PropertyChangedCallback(OnValueChanged)));

        protected static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            ImageWall i = obj as ImageWall;
            i.InvalidateArrange();
        }

        public double ZHoverValue
        {
            get { return (double)GetValue(ZHoverValueProperty); }
            set { SetValue(ZHoverValueProperty, value); }
        }

        public static readonly DependencyProperty ZHoverValueProperty =
            DependencyProperty.Register(
                "ZHoverValue", 
                typeof(double), 
                typeof(ImageWall),
                new PropertyMetadata((double)C_DefaultZHover, null));

        public bool ShowShadow
        {
            get { return (bool)GetValue(ShowShadowProperty); }
            set { SetValue(ShowShadowProperty, value); }
        }

        public static readonly DependencyProperty ShowShadowProperty =
            DependencyProperty.Register(
                "ShowShadow", 
                typeof(bool), 
                typeof(ImageWall),
                new PropertyMetadata((bool)C_DefaultShowShadow, new PropertyChangedCallback(OnValueChanged)));

        #endregion

    }
}
